package grape.attend.service.user.clock;

import cn.hutool.core.date.DateUnit;
import grape.attend.service.user.api.IUserClockService;
import grape.attend.service.user.po.UserClock;
import grape.composite.service.workcalendar.po.WorkCalendar;
import grape.common.tools.ToolService;
import org.springframework.stereotype.Component;

/**
 * 用户下班打卡类型支持服务
 * Created by yangwei
 * Created at 2020/5/26 16:25
 */
@Component
public class UserClockOffClockService implements ToolService {

    /**
     * 正常打卡
     * @param preClockParam
     * @param userClock
     * @return
     */
    public UserClock normalClock(PreClockParam preClockParam, UserClock userClock) {
        long shouldClockAt = preClockParam.getClasseEndAt();
        CalendarHandleDto calendarHandleDto = calendarHandle(preClockParam, userClock,shouldClockAt);
        if (calendarHandleDto.getIsReturn()) {
            return userClock;
        }else if (calendarHandleDto.getShouldClockAt() != null) {
            shouldClockAt = calendarHandleDto.getShouldClockAt();
        }
        // 早退
        if(preClockParam.getNow() < shouldClockAt){
            Integer earlyLeaveTime = IUserClockService.getIntervalMinutes(shouldClockAt , preClockParam.getNow());
            userClock.setIsOffClockLeaveEarly(true);
            userClock.setOffClockLeaveEarlyTime(earlyLeaveTime);
        }else {
            // 晚走
            Integer lateLeaveTime = IUserClockService.getIntervalMinutes(preClockParam.getNow(),shouldClockAt);
            if (preClockParam.getClock().getIsNextDayLate()) {
                // 如果达到了晚走的条件
                if (lateLeaveTime >= preClockParam.getClock().getLateLeave()) {
                    userClock.setIsOffClockLateLeave(true);
                    userClock.setOffClockLateLeave(lateLeaveTime);
                }
            }

        }
        userClock.setOffClockShouldAt(shouldClockAt);
        return userClock;
    }

    /**
     * 早到早走，晚到晚走
     * @param preClockParam
     * @param userClock
     * @return
     */
    public UserClock allowEarlEarlyLateLate(PreClockParam preClockParam,UserClock userClock) {
        long shouldClockAt = preClockParam.getClasseEndAt();
        CalendarHandleDto calendarHandleDto = calendarHandle(preClockParam, userClock,shouldClockAt);
        if (calendarHandleDto.getIsReturn()) {
            return userClock;
        }else if (calendarHandleDto.getShouldClockAt() != null) {
            shouldClockAt = calendarHandleDto.getShouldClockAt();
        }
        // 早退
        if(preClockParam.getNow() < shouldClockAt){
            Integer earlyLeaveTime = IUserClockService.getIntervalMinutes(shouldClockAt , preClockParam.getNow());

            // 如果上班没有打卡,则下班按正常点计算
            if (preClockParam.getDbUserClock() == null || preClockParam.getDbUserClock().getOnClockAt() == null) {
                userClock.setIsOffClockLeaveEarly(true);
                userClock.setOffClockLeaveEarlyTime(earlyLeaveTime);
            }else {
                // 上班打卡了
                // 判断上班是否早到
                if (preClockParam.getDbUserClock().getOnClockAt() < preClockParam.getClasseStartAt()) {
                    // 早到的时间
                    Integer earlyArriveTime = IUserClockService.getIntervalMinutes(preClockParam.getClasseStartAt() , preClockParam.getDbUserClock().getOnClockAt());
                    // 最大早走时间
                    Integer limitEarlyLeaveTime = earlyArriveTime > preClockParam.getClock().getEarlyLeaveMax() ? preClockParam.getClock().getEarlyLeaveMax() : earlyArriveTime;
                    shouldClockAt -= limitEarlyLeaveTime * DateUnit.MINUTE.getMillis();
                    // 如果早走时间大于最大限制早走时间
                    if (earlyLeaveTime > limitEarlyLeaveTime) {
                        userClock.setIsOffClockLeaveEarly(true);
                        userClock.setOffClockLeaveEarlyTime(earlyLeaveTime - limitEarlyLeaveTime);
                    }
                }else {
                    // 如果没有早到，那么下班算早退
                    userClock.setIsOffClockLeaveEarly(true);
                    userClock.setOffClockLeaveEarlyTime(earlyLeaveTime);
                }
            }
        }else {
            // 晚走
            Integer lateLeaveTime = IUserClockService.getIntervalMinutes(preClockParam.getNow() , shouldClockAt);

            // 如果上班打卡了，判断上班是否晚到
            if (preClockParam.getDbUserClock() != null || preClockParam.getDbUserClock().getOnClockAt() != null) {
                // 如果上班迟到，肯定是晚到了，因为上班打卡已处理晚到最大时长
                Integer lateTime = null;
                if (preClockParam.getDbUserClock().getIsOnClockLate()) {
                    lateTime = preClockParam.getClock().getLateArriveMax();
                }else {
                    // 上班未迟到，但有迟到的时长，也是晚到
                    if(preClockParam.getDbUserClock().getOnClockLateTime() != null && preClockParam.getDbUserClock().getOnClockLateTime() > 0){
                        // 晚到
                        lateTime = preClockParam.getDbUserClock().getOnClockLateTime();
                    }
                }
                if (lateTime != null) {
                    shouldClockAt += lateTime * DateUnit.MINUTE.getMillis();
                    // 晚到时长不为空，那么晚走应该打卡时间应该加上晚到时长
                    if(lateLeaveTime < lateTime){
                        userClock.setIsOffClockLeaveEarly(true);
                        userClock.setOffClockLeaveEarlyTime(lateTime - lateLeaveTime);
                    }
                }
            }
            if (preClockParam.getClock().getIsNextDayLate()) {
                Integer lateLeave = IUserClockService.getIntervalMinutes(preClockParam.getNow(),shouldClockAt);

                if(lateLeave > preClockParam.getClock().getLateLeave()){
                    userClock.setIsOffClockLateLeave(true);
                    userClock.setOffClockLateLeave(lateLeave);
                }

            }

        }
        userClock.setOffClockShouldAt(shouldClockAt);
        return userClock;
    }

    /**
     * 可以早走晚到几分钟
     * @param preClockParam
     * @param userClock
     * @return
     */
    public UserClock allowEarlLate(PreClockParam preClockParam,UserClock userClock) {
        long shouldClockAt = preClockParam.getClasseEndAt();
        CalendarHandleDto calendarHandleDto = calendarHandle(preClockParam, userClock,shouldClockAt);
        if (calendarHandleDto.getIsReturn()) {
            return userClock;
        }else if (calendarHandleDto.getShouldClockAt() != null) {
            shouldClockAt = calendarHandleDto.getShouldClockAt();
        }
        // 早退
        if(preClockParam.getNow() < shouldClockAt){
            Integer earlyLeaveTime = IUserClockService.getIntervalMinutes(shouldClockAt , preClockParam.getNow());
            // 如果早走的分钟数超过了设置的分钟数，则算早退了
            if(earlyLeaveTime > preClockParam.getClock().getEarlyLeaveMax()){
                userClock.setIsOffClockLeaveEarly(true);
                userClock.setOffClockLeaveEarlyTime(earlyLeaveTime - preClockParam.getClock().getEarlyLeaveMax());
            }
        }else {
            // 晚走，应该打卡时间这里没有减去允许早走几分钟的时间
            Integer lateLeaveTime = IUserClockService.getIntervalMinutes(preClockParam.getNow() , shouldClockAt);
            if (preClockParam.getClock().getIsNextDayLate()) {
                // 如果达到了晚走的条件
                if (lateLeaveTime >= preClockParam.getClock().getLateLeave()) {
                    userClock.setIsOffClockLateLeave(true);
                    userClock.setOffClockLateLeave(lateLeaveTime);
                }
            }
        }

        return userClock;
    }

    /**
     * 工作日历设置考虑
     * @param preClockParam
     * @param userClock
     * @param shouldClockAt
     * @return
     */
    private CalendarHandleDto calendarHandle(PreClockParam preClockParam,UserClock userClock,Long shouldClockAt){
        CalendarHandleDto calendarHandleDto = new CalendarHandleDto();
        calendarHandleDto.setShouldClockAt(shouldClockAt);
        // 如果班次日期休息，不算早退
        if (preClockParam.getClasseDatewWorkCalendar() != null) {
            // 设置了全天休息，打卡正常
            if (preClockParam.getClasseDateType().name().equals(WorkCalendar.Type.all_day_rest.name())) {
                calendarHandleDto.setIsReturn(true);
            }
            // 设置了下午休息，那么打卡时间应该在开始之后
            else  if (preClockParam.getClasseDateType().name().equals(WorkCalendar.Type.day_am_work_pm_rest.name())) {
                if (preClockParam.getClasse().getIsHasRest()) {
                    calendarHandleDto.setShouldClockAt(preClockParam.getClasseRestStartAt());
                }else {
                    // 如果没有设置休息，那么打卡时间缩短工作时长的一半
                    calendarHandleDto.setShouldClockAt(shouldClockAt - (preClockParam.getClasseEndAt() - preClockParam.getClasseStartAt())/2);
                }
            }
        }else {
            // 如果没有设置，按自然日，不是工作日正常
            if(!preClockParam.getClasseDateDateType().name().equals(WorkCalendar.DateType.date_type_work.name())){
                calendarHandleDto.setIsReturn(true);
            }
        }
        userClock.setOffClockShouldAt(calendarHandleDto.getShouldClockAt());
        return calendarHandleDto;
    }
}
